home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / rpcinfo / rpcinfo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-11-17  |  15.4 KB  |  630 lines

  1. /* @(#)rpcinfo.c    1.5 87/11/20 3.9 RPCSRC */
  2. #ifndef lint
  3. static    char sccsid[] = "@(#)rpcinfo.c 1.22 87/08/12 SMI";
  4. #endif
  5.  
  6. /*
  7.  * Copyright (C) 1986, Sun Microsystems, Inc.
  8.  */
  9.  
  10. /*
  11.  * rpcinfo: ping a particular rpc program
  12.  *     or dump the portmapper
  13.  */
  14.  
  15. /*
  16.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  17.  * unrestricted use provided that this legend is included on all tape
  18.  * media and as a part of the software program in whole or part.  Users
  19.  * may copy or modify Sun RPC without charge, but are not authorized
  20.  * to license or distribute it to anyone else except as part of a product or
  21.  * program developed by the user.
  22.  * 
  23.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  24.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  25.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  26.  * 
  27.  * Sun RPC is provided with no support and without any obligation on the
  28.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  29.  * modification or enhancement.
  30.  * 
  31.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  32.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  33.  * OR ANY PART THEREOF.
  34.  * 
  35.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  36.  * or profits or other special, indirect and consequential damages, even if
  37.  * Sun has been advised of the possibility of such damages.
  38.  * 
  39.  * Sun Microsystems, Inc.
  40.  * 2550 Garcia Avenue
  41.  * Mountain View, California  94043
  42.  */
  43.  
  44. #include <rpc/rpc.h>
  45. #include <stdio.h>
  46. #include <sys/socket.h>
  47. #include <sys/time.h>
  48. #include <netdb.h>
  49. #include <rpc/pmap_prot.h>
  50. #include <rpc/pmap_clnt.h>
  51. #include <signal.h>
  52. #include <ctype.h>
  53.  
  54. #define MAXHOSTLEN 256
  55.  
  56. #define    MIN_VERS    ((u_long) 0)
  57. #define    MAX_VERS    ((u_long) 4294967295L)
  58.  
  59. static void    udpping(/*u_short portflag, int argc, char **argv*/);
  60. static void    tcpping(/*u_short portflag, int argc, char **argv*/);
  61. static int    pstatus(/*CLIENT *client, u_long prognum, u_long vers*/);
  62. static void    pmapdump(/*int argc, char **argv*/);
  63. static bool_t    reply_proc(/*void *res, struct sockaddr_in *who*/);
  64. static void    brdcst(/*int argc, char **argv*/);
  65. static void    usage(/*void*/);
  66. static u_long    getprognum(/*char *arg*/);
  67. static u_long    getvers(/*char *arg*/);
  68. static void    get_inet_address(/*struct sockaddr_in *addr, char *host*/);
  69. extern u_long inet_addr();  /* in 4.2BSD, arpa/inet.h called that a in_addr */
  70. extern char *inet_ntoa();
  71.  
  72. /*
  73.  * Functions to be performed.
  74.  */
  75. #define    NONE        0    /* no function */
  76. #define    PMAPDUMP    1    /* dump portmapper registrations */
  77. #define    TCPPING        2    /* ping TCP service */
  78. #define    UDPPING        3    /* ping UDP service */
  79. #define    BRDCST        4    /* ping broadcast UDP service */
  80.  
  81. int
  82. main(argc, argv)
  83.     int argc;
  84.     char **argv;
  85. {
  86.     register int c;
  87.     extern char *optarg;
  88.     extern int optind;
  89.     int errflg;
  90.     int function;
  91.     u_short portnum;
  92.  
  93.     function = NONE;
  94.     portnum = 0;
  95.     errflg = 0;
  96.     while ((c = getopt(argc, argv, "ptubn:")) != EOF) {
  97.         switch (c) {
  98.  
  99.         case 'p':
  100.             if (function != NONE)
  101.                 errflg = 1;
  102.             else
  103.                 function = PMAPDUMP;
  104.             break;
  105.  
  106.         case 't':
  107.             if (function != NONE)
  108.                 errflg = 1;
  109.             else
  110.                 function = TCPPING;
  111.             break;
  112.  
  113.         case 'u':
  114.             if (function != NONE)
  115.                 errflg = 1;
  116.             else
  117.                 function = UDPPING;
  118.             break;
  119.  
  120.         case 'b':
  121.             if (function != NONE)
  122.                 errflg = 1;
  123.             else
  124.                 function = BRDCST;
  125.             break;
  126.  
  127.         case 'n':
  128.             portnum = (u_short) atoi(optarg);   /* hope we don't get bogus # */
  129.             break;
  130.  
  131.         case '?':
  132.             errflg = 1;
  133.         }
  134.     }
  135.  
  136.     if (errflg || function == NONE) {
  137.         usage();
  138.         return (1);
  139.     }
  140.  
  141.     switch (function) {
  142.  
  143.     case PMAPDUMP:
  144.         if (portnum != 0) {
  145.             usage();
  146.             return (1);
  147.         }
  148.         pmapdump(argc - optind, argv + optind);
  149.         break;
  150.  
  151.     case UDPPING:
  152.         udpping(portnum, argc - optind, argv + optind);
  153.         break;
  154.  
  155.     case TCPPING:
  156.         tcpping(portnum, argc - optind, argv + optind);
  157.         break;
  158.  
  159.     case BRDCST:
  160.         if (portnum != 0) {
  161.             usage();
  162.             return (1);
  163.         }
  164.         brdcst(argc - optind, argv + optind);
  165.         break;
  166.     }
  167.  
  168.     return (0);
  169. }
  170.         
  171. static void
  172. udpping(portnum, argc, argv)
  173.     u_short portnum;
  174.     int argc;
  175.     char **argv;
  176. {
  177.     struct timeval to;
  178.     struct sockaddr_in addr;
  179.     enum clnt_stat rpc_stat;
  180.     CLIENT *client;
  181.     u_long prognum, vers, minvers, maxvers;
  182.     int sock = RPC_ANYSOCK;
  183.     struct rpc_err rpcerr;
  184.     int failure;
  185.     
  186.     if (argc < 2 || argc > 3) {
  187.         usage();
  188.         exit(1);
  189.     }
  190.     prognum = getprognum(argv[1]);
  191.     get_inet_address(&addr, argv[0]);
  192.     /* Open the socket here so it will survive calls to clnt_destroy */
  193.     sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  194.     if (sock < 0) {
  195.         perror("rpcinfo: socket");
  196.         exit(1);
  197.     }
  198.     failure = 0;
  199.     if (argc == 2) {
  200.         /*
  201.          * A call to version 0 should fail with a program/version
  202.          * mismatch, and give us the range of versions supported.
  203.          */
  204.         addr.sin_port = htons(portnum);
  205.         to.tv_sec = 5;
  206.         to.tv_usec = 0;
  207.         if ((client = clntudp_create(&addr, prognum, (u_long)0,
  208.             to, &sock)) == NULL) {
  209.             clnt_pcreateerror("rpcinfo");
  210.             printf("program %lu is not available\n",
  211.                 prognum);
  212.             exit(1);
  213.         }
  214.         to.tv_sec = 10;
  215.         to.tv_usec = 0;
  216.         rpc_stat = clnt_call(client, NULLPROC, xdr_void, (char *)NULL,
  217.             xdr_void, (char *)NULL, to);
  218.         if (rpc_stat == RPC_PROGVERSMISMATCH) {
  219.             clnt_geterr(client, &rpcerr);
  220.             minvers = rpcerr.re_vers.low;
  221.             maxvers = rpcerr.re_vers.high;
  222.         } else if (rpc_stat == RPC_SUCCESS) {
  223.             /*
  224.              * Oh dear, it DOES support version 0.
  225.              * Let's try version MAX_VERS.
  226.              */
  227.             addr.sin_port = htons(portnum);
  228.             to.tv_sec = 5;
  229.             to.tv_usec = 0;
  230.             if ((client = clntudp_create(&addr, prognum, MAX_VERS,
  231.                 to, &sock)) == NULL) {
  232.                 clnt_pcreateerror("rpcinfo");
  233.                 printf("program %lu version %lu is not available\n",
  234.                     prognum, MAX_VERS);
  235.                 exit(1);
  236.             }
  237.             to.tv_sec = 10;
  238.             to.tv_usec = 0;
  239.             rpc_stat = clnt_call(client, NULLPROC, xdr_void,
  240.                 (char *)NULL, xdr_void, (char *)NULL, to);
  241.             if (rpc_stat == RPC_PROGVERSMISMATCH) {
  242.                 clnt_geterr(client, &rpcerr);
  243.                 minvers = rpcerr.re_vers.low;
  244.                 maxvers = rpcerr.re_vers.high;
  245.             } else if (rpc_stat == RPC_SUCCESS) {
  246.                 /*
  247.                  * It also supports version MAX_VERS.
  248.                  * Looks like we have a wise guy.
  249.                  * OK, we give them information on all
  250.                  * 4 billion versions they support...
  251.                  */
  252.                 minvers = 0;
  253.                 maxvers = MAX_VERS;
  254.             } else {
  255.                 (void) pstatus(client, prognum, MAX_VERS);
  256.                 exit(1);
  257.             }
  258.         } else {
  259.             (void) pstatus(client, prognum, (u_long)0);
  260.             exit(1);
  261.         }
  262.         clnt_destroy(client);
  263.         for (vers = minvers; vers <= maxvers; vers++) {
  264.             addr.sin_port = htons(portnum);
  265.             to.tv_sec = 5;
  266.             to.tv_usec = 0;
  267.             if ((client = clntudp_create(&addr, prognum, vers,
  268.                 to, &sock)) == NULL) {
  269.                 clnt_pcreateerror("rpcinfo");
  270.                 printf("program %lu version %lu is not available\n",
  271.                     prognum, vers);
  272.                 exit(1);
  273.             }
  274.             to.tv_sec = 10;
  275.             to.tv_usec = 0;
  276.             rpc_stat = clnt_call(client, NULLPROC, xdr_void,
  277.                 (char *)NULL, xdr_void, (char *)NULL, to);
  278.             if (pstatus(client, prognum, vers) < 0)
  279.                 failure = 1;
  280.             clnt_destroy(client);
  281.         }
  282.     }
  283.     else {
  284.         vers = getvers(argv[2]);
  285.         addr.sin_port = htons(portnum);
  286.         to.tv_sec = 5;
  287.         to.tv_usec = 0;
  288.         if ((client = clntudp_create(&addr, prognum, vers,
  289.             to, &sock)) == NULL) {
  290.             clnt_pcreateerror("rpcinfo");
  291.             printf("program %lu version %lu is not available\n",
  292.                 prognum, vers);
  293.             exit(1);
  294.         }
  295.         to.tv_sec = 10;
  296.         to.tv_usec = 0;
  297.         rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL,
  298.             xdr_void, (char *)NULL, to);
  299.         if (pstatus(client, prognum, vers) < 0)
  300.             failure = 1;
  301.     }
  302.     (void) close(sock); /* Close it up again */
  303.     if (failure)
  304.         exit(1);
  305. }
  306.  
  307. static void
  308. tcpping(portnum, argc, argv)
  309.     u_short portnum;
  310.     int argc;
  311.     char **argv;
  312. {
  313.     struct timeval to;
  314.     struct sockaddr_in addr;
  315.     enum clnt_stat rpc_stat;
  316.     CLIENT *client;
  317.     u_long prognum, vers, minvers, maxvers;
  318.     int sock = RPC_ANYSOCK;
  319.     struct rpc_err rpcerr;
  320.     int failure;
  321.  
  322.     if (argc < 2 || argc > 3) {
  323.         usage();
  324.         exit(1);
  325.     }
  326.     prognum = getprognum(argv[1]);
  327.     get_inet_address(&addr, argv[0]);
  328.     failure = 0;
  329.     if (argc == 2) {
  330.         /*
  331.          * A call to version 0 should fail with a program/version
  332.          * mismatch, and give us the range of versions supported.
  333.          */
  334.         addr.sin_port = htons(portnum);
  335.         if ((client = clnttcp_create(&addr, prognum, MIN_VERS,
  336.             &sock, 0, 0)) == NULL) {
  337.             clnt_pcreateerror("rpcinfo");
  338.             printf("program %lu is not available\n",
  339.                 prognum);
  340.             exit(1);
  341.         }
  342.         to.tv_sec = 10;
  343.         to.tv_usec = 0;
  344.         rpc_stat = clnt_call(client, NULLPROC, xdr_void, (char *)NULL,
  345.             xdr_void, (char *)NULL, to);
  346.         if (rpc_stat == RPC_PROGVERSMISMATCH) {
  347.             clnt_geterr(client, &rpcerr);
  348.             minvers = rpcerr.re_vers.low;
  349.             maxvers = rpcerr.re_vers.high;
  350.         } else if (rpc_stat == RPC_SUCCESS) {
  351.             /*
  352.              * Oh dear, it DOES support version 0.
  353.              * Let's try version MAX_VERS.
  354.              */
  355.             addr.sin_port = htons(portnum);
  356.             if ((client = clnttcp_create(&addr, prognum, MAX_VERS,
  357.                 &sock, 0, 0)) == NULL) {
  358.                 clnt_pcreateerror("rpcinfo");
  359.                 printf("program %lu version %lu is not available\n",
  360.                     prognum, MAX_VERS);
  361.                 exit(1);
  362.             }
  363.             to.tv_sec = 10;
  364.             to.tv_usec = 0;
  365.             rpc_stat = clnt_call(client, NULLPROC, xdr_void,
  366.                 (char *)NULL, xdr_void, (char *)NULL, to);
  367.             if (rpc_stat == RPC_PROGVERSMISMATCH) {
  368.                 clnt_geterr(client, &rpcerr);
  369.                 minvers = rpcerr.re_vers.low;
  370.                 maxvers = rpcerr.re_vers.high;
  371.             } else if (rpc_stat == RPC_SUCCESS) {
  372.                 /*
  373.                  * It also supports version MAX_VERS.
  374.                  * Looks like we have a wise guy.
  375.                  * OK, we give them information on all
  376.                  * 4 billion versions they support...
  377.                  */
  378.                 minvers = 0;
  379.                 maxvers = MAX_VERS;
  380.             } else {
  381.                 (void) pstatus(client, prognum, MAX_VERS);
  382.                 exit(1);
  383.             }
  384.         } else {
  385.             (void) pstatus(client, prognum, MIN_VERS);
  386.             exit(1);
  387.         }
  388.         clnt_destroy(client);
  389.         (void) close(sock);
  390.         sock = RPC_ANYSOCK; /* Re-initialize it for later */
  391.         for (vers = minvers; vers <= maxvers; vers++) {
  392.             addr.sin_port = htons(portnum);
  393.             if ((client = clnttcp_create(&addr, prognum, vers,
  394.                 &sock, 0, 0)) == NULL) {
  395.                 clnt_pcreateerror("rpcinfo");
  396.                 printf("program %lu version %lu is not available\n",
  397.                     prognum, vers);
  398.                 exit(1);
  399.             }
  400.             to.tv_usec = 0;
  401.             to.tv_sec = 10;
  402.             rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL,
  403.                 xdr_void, (char *)NULL, to);
  404.             if (pstatus(client, prognum, vers) < 0)
  405.                 failure = 1;
  406.             clnt_destroy(client);
  407.             (void) close(sock);
  408.             sock = RPC_ANYSOCK;
  409.         }
  410.     }
  411.     else {
  412.         vers = getvers(argv[2]);
  413.         addr.sin_port = htons(portnum);
  414.         if ((client = clnttcp_create(&addr, prognum, vers, &sock,
  415.             0, 0)) == NULL) {
  416.             clnt_pcreateerror("rpcinfo");
  417.             printf("program %lu version %lu is not available\n",
  418.                 prognum, vers);
  419.             exit(1);
  420.         }
  421.         to.tv_usec = 0;
  422.         to.tv_sec = 10;
  423.         rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL,
  424.             xdr_void, (char *)NULL, to);
  425.         if (pstatus(client, prognum, vers) < 0)
  426.             failure = 1;
  427.     }
  428.     if (failure)
  429.         exit(1);
  430. }
  431.  
  432. /*
  433.  * This routine should take a pointer to an "rpc_err" structure, rather than
  434.  * a pointer to a CLIENT structure, but "clnt_perror" takes a pointer to
  435.  * a CLIENT structure rather than a pointer to an "rpc_err" structure.
  436.  * As such, we have to keep the CLIENT structure around in order to print
  437.  * a good error message.
  438.  */
  439. static int
  440. pstatus(client, prognum, vers)
  441.     register CLIENT *client;
  442.     u_long prognum;
  443.     u_long vers;
  444. {
  445.     struct rpc_err rpcerr;
  446.  
  447.     clnt_geterr(client, &rpcerr);
  448.     if (rpcerr.re_status != RPC_SUCCESS) {
  449.         clnt_perror(client, "rpcinfo");
  450.         printf("program %lu version %lu is not available\n",
  451.             prognum, vers);
  452.         return (-1);
  453.     } else {
  454.         printf("program %lu version %lu ready and waiting\n",
  455.             prognum, vers);
  456.         return (0);
  457.     }
  458. }
  459.  
  460. static void
  461. pmapdump(argc, argv)
  462.     int argc;
  463.     char **argv;
  464. {
  465.     struct sockaddr_in server_addr;
  466.     register struct hostent *hp;
  467.     struct pmaplist *head = NULL;
  468.     int socket = RPC_ANYSOCK;
  469.     struct timeval minutetimeout;
  470.     register CLIENT *client;
  471.     struct rpcent *rpc;
  472.     
  473.     if (argc > 1) {
  474.         usage();
  475.         exit(1);
  476.     }
  477.     if (argc == 1)
  478.         get_inet_address(&server_addr, argv[0]);
  479.     else {
  480.         bzero((char *)&server_addr, sizeof server_addr);
  481.         server_addr.sin_family = AF_INET;
  482.         if ((hp = gethostbyname("localhost")) != NULL)
  483.             bcopy(hp->h_addr, (caddr_t)&server_addr.sin_addr,
  484.                 hp->h_length);
  485.         else
  486.             server_addr.sin_addr.s_addr = inet_addr("0.0.0.0");
  487.     }
  488.     minutetimeout.tv_sec = 60;
  489.     minutetimeout.tv_usec = 0;
  490.     server_addr.sin_port = htons(PMAPPORT);
  491.     if ((client = clnttcp_create(&server_addr, PMAPPROG,
  492.         PMAPVERS, &socket, 50, 500)) == NULL) {
  493.         clnt_pcreateerror("rpcinfo: can't contact portmapper");
  494.         exit(1);
  495.     }
  496.     if (clnt_call(client, PMAPPROC_DUMP, xdr_void, NULL,
  497.         xdr_pmaplist, &head, minutetimeout) != RPC_SUCCESS) {
  498.         fprintf(stderr, "rpcinfo: can't contact portmapper: ");
  499.         clnt_perror(client, "rpcinfo");
  500.         exit(1);
  501.     }
  502.     if (head == NULL) {
  503.         printf("No remote programs registered.\n");
  504.     } else {
  505.         printf("   program vers proto   port\n");
  506.         for (; head != NULL; head = head->pml_next) {
  507.             printf("%10ld%5ld",
  508.                 head->pml_map.pm_prog,
  509.                 head->pml_map.pm_vers);
  510.             if (head->pml_map.pm_prot == IPPROTO_UDP)
  511.                 printf("%6s",  "udp");
  512.             else if (head->pml_map.pm_prot == IPPROTO_TCP)
  513.                 printf("%6s", "tcp");
  514.             else
  515.                 printf("%6ld",  head->pml_map.pm_prot);
  516.             printf("%7ld",  head->pml_map.pm_port);
  517.             rpc = getrpcbynumber(head->pml_map.pm_prog);
  518.             if (rpc)
  519.                 printf("  %s\n", rpc->r_name);
  520.             else
  521.                 printf("\n");
  522.         }
  523.     }
  524. }
  525.  
  526. /* 
  527.  * reply_proc collects replies from the broadcast. 
  528.  * to get a unique list of responses the output of rpcinfo should
  529.  * be piped through sort(1) and then uniq(1).
  530.  */
  531.  
  532. /*ARGSUSED*/
  533. static bool_t
  534. reply_proc(res, who)
  535.     void *res;        /* Nothing comes back */
  536.     struct sockaddr_in *who; /* Who sent us the reply */
  537. {
  538.     register struct hostent *hp;
  539.  
  540.     hp = gethostbyaddr((char *) &who->sin_addr, sizeof who->sin_addr,
  541.         AF_INET);
  542.     printf("%s %s\n", inet_ntoa(who->sin_addr),
  543.         (hp == NULL) ? "(unknown)" : hp->h_name);
  544.     return(FALSE);
  545. }
  546.  
  547. static void
  548. brdcst(argc, argv)
  549.     int argc;
  550.     char **argv;
  551. {
  552.     enum clnt_stat rpc_stat;
  553.     u_long prognum, vers;
  554.  
  555.     if (argc != 2) {
  556.         usage();
  557.         exit(1);
  558.     }
  559.     prognum = getprognum(argv[0]);
  560.     vers = getvers(argv[1]);
  561.     rpc_stat = clnt_broadcast(prognum, vers, NULLPROC, xdr_void,
  562.         (char *)NULL, xdr_void, (char *)NULL, reply_proc);
  563.     if ((rpc_stat != RPC_SUCCESS) && (rpc_stat != RPC_TIMEDOUT)) {
  564.         fprintf(stderr, "rpcinfo: broadcast failed: %s\n",
  565.             clnt_sperrno(rpc_stat));
  566.         exit(1);
  567.     }
  568.     exit(0);
  569. }
  570.  
  571. static void
  572. usage()
  573. {
  574.     fprintf(stderr, "Usage: rpcinfo [ -n portnum ] -u host prognum [ versnum ]\n");
  575.     fprintf(stderr, "       rpcinfo [ -n portnum ] -t host prognum [ versnum ]\n");
  576.     fprintf(stderr, "       rpcinfo -p [ host ]\n");
  577.     fprintf(stderr, "       rpcinfo -b prognum versnum\n");
  578. }
  579.  
  580. static u_long
  581. getprognum(arg)
  582.     char *arg;
  583. {
  584.     register struct rpcent *rpc;
  585.     register u_long prognum;
  586.  
  587.     if (isalpha(*arg)) {
  588.         rpc = getrpcbyname(arg);
  589.         if (rpc == NULL) {
  590.             fprintf(stderr, "rpcinfo: %s is unknown service\n",
  591.                 arg);
  592.             exit(1);
  593.         }
  594.         prognum = rpc->r_number;
  595.     } else {
  596.         prognum = (u_long) atoi(arg);
  597.     }
  598.  
  599.     return (prognum);
  600. }
  601.  
  602. static u_long
  603. getvers(arg)
  604.     char *arg;
  605. {
  606.     register u_long vers;
  607.  
  608.     vers = (int) atoi(arg);
  609.     return (vers);
  610. }
  611.  
  612. static void
  613. get_inet_address(addr, host)
  614.     struct sockaddr_in *addr;
  615.     char *host;
  616. {
  617.     register struct hostent *hp;
  618.  
  619.     bzero((char *)addr, sizeof *addr);
  620.     addr->sin_addr.s_addr = (u_long) inet_addr(host);
  621.     if (addr->sin_addr.s_addr == -1 || addr->sin_addr.s_addr == 0) {
  622.         if ((hp = gethostbyname(host)) == NULL) {
  623.             fprintf(stderr, "rpcinfo: %s is unknown host\n", host);
  624.             exit(1);
  625.         }
  626.         bcopy(hp->h_addr, (char *)&addr->sin_addr, hp->h_length);
  627.     }
  628.     addr->sin_family = AF_INET;
  629. }
  630.